package org.googlecode.viewt.core.tools.formbean;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.exolab.castor.xml.MarshalException;
import org.exolab.castor.xml.ValidationException;
import org.googlecode.viewt.core.tools.formbean.types.FormBeanDef;
import org.googlecode.viewt.core.tools.formbean.types.FormBeans;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;



public class FormBeanCfgRepository {
	private static Logger logger = LoggerFactory
			.getLogger(FormBeanCfgRepository.class);

	private Map formbeanMap = new HashMap();

	private FormBeans mainDef = null;

	private String prePackName = null;

	private String mainDefFile = null;

	public void setMainDef(String cfgFile, String prePackName) {
		this.mainDefFile = cfgFile;
		this.prePackName = prePackName;

		logger.debug("Begin load main formbean config file:" + cfgFile);
		try {
			Reader in = new InputStreamReader(new FileInputStream(cfgFile));
			this.mainDef = FormBeans.unmarshal(in);
		} catch (FileNotFoundException fnfEx) {
			logger.error("Can not find formbean config:" + cfgFile
					+ ", check your config", fnfEx);
			return;
		} catch (MarshalException marshalEx) {
			logger.error("Unmarshal formbean config:" + cfgFile
					+ " fail, check your config", marshalEx);
			return;
		} catch (ValidationException validateEx) {
			logger.error("Validate formbean config:" + cfgFile
					+ " fail, check your config", validateEx);
			return;
		}

		addFormBeanConfig(this.mainDef.getFormBeanDef());

		logger.debug("Set main formbean config done.");
	}

	public FormBeans getMainDef() {
		return this.mainDef;
	}

	public String getMainDefFile() {
		return this.mainDefFile;
	}

	public String getPrePackName() {
		return this.prePackName;
	}

	public void addFormBeanConfig(String cfgFile) {
		if (this.mainDefFile == null) {
			logger.error("main definition not set, set it first");
			return;
		}

		try {
			Reader in = new InputStreamReader(new FileInputStream(cfgFile));
			FormBeans formbeans = FormBeans.unmarshal(in);
			addFormBeanConfig(formbeans.getFormBeanDef());
		} catch (FileNotFoundException fnfEx) {
			logger.error("Can not find formbean config:" + cfgFile
					+ ", check your config", fnfEx);
			return;
		} catch (MarshalException marshalEx) {
			logger.error("Unmarshal formbean config:" + cfgFile
					+ " fail, check your config", marshalEx);
			return;
		} catch (ValidationException validateEx) {
			logger.error("Validate formbean config:" + cfgFile
					+ " fail, check your config", validateEx);
			return;
		}
	}

	public void addFormBeanConfig(FormBeanDef formbeanDef) {
		if (formbeanDef == null) {
			return;
		}
		String className = formbeanDef.getClassName();
		if (!(this.formbeanMap.containsKey(className)))
			this.formbeanMap.put(className, formbeanDef);
	}

	public void addFormBeanConfig(FormBeanDef[] formbeanDefs) {
		int len = (formbeanDefs == null) ? 0 : formbeanDefs.length;
		for (int i = 0; i < len; ++i)
			addFormBeanConfig(formbeanDefs[i]);
	}

	public FormBeanDef getFormBeanConfig(String className) {
		FormBeanDef formbeanDef = (FormBeanDef) this.formbeanMap.get(className);
		if (formbeanDef == null) {
			String depCfgFile = FormBeanUtil.findDepCfgFile(this.mainDefFile,
					className);
			if (depCfgFile != null) {
				logger.debug("retry dependent formbean config file:"
						+ depCfgFile);
				try {
					Reader in = new InputStreamReader(new FileInputStream(
							depCfgFile));
					FormBeans formbeans = FormBeans.unmarshal(in);
					addFormBeanConfig(formbeans.getFormBeanDef());
					formbeanDef = (FormBeanDef) this.formbeanMap.get(className);
				} catch (FileNotFoundException fnfEx) {
					logger.error("Can not find formbean config:" + depCfgFile
							+ ", check your config", fnfEx);
					return null;
				} catch (MarshalException marshalEx) {
					logger.error("Unmarshal formbean config:" + depCfgFile
							+ " fail, check your config", marshalEx);
					return null;
				} catch (ValidationException validateEx) {
					logger.error("Validate formbean config:" + depCfgFile
							+ " fail, check your config", validateEx);
					return null;
				}
			}
		}

		return formbeanDef;
	}

	public FormBeanDef[] getCurFormBeanConfig() {
		return getFormBeanConfigByModule(getProjectName(), getModuleName());
	}

	public FormBeanDef[] getFormBeanConfigByModule(String projectName,
			String moduleName) {
		List confList = new ArrayList();
		for (Iterator iterator = this.formbeanMap.keySet().iterator(); iterator
				.hasNext();) {
			String className = (String) iterator.next();
			if ((!(projectName.equals(FormBeanUtil
					.getFormBeanProject(className))))
					|| (!(moduleName.equals(FormBeanUtil
							.getFormBeanModule(className)))))
				continue;
			confList.add(this.formbeanMap.get(className));
		}

		return ((FormBeanDef[]) confList.toArray(new FormBeanDef[0]));
	}

	public String[] formbeanAncestorClass(String className) {
		List ancestorList = new ArrayList();
		FormBeanDef formbeanDef = getFormBeanConfig(className);
		while ((formbeanDef != null) && (formbeanDef.getParentClass() != null)) {
			String parentClass = formbeanDef.getParentClass();
			ancestorList.add(parentClass);
			formbeanDef = getFormBeanConfig(parentClass);
		}

		String[] ancestors = new String[ancestorList.size()];
		for (int i = 0; i < ancestors.length; ++i) {
			ancestors[i] = ((String) ancestorList.get(i));
		}
		return ancestors;
	}

	public String getProjectName() {
		return ((this.mainDef == null) ? null : this.mainDef.getProjectName());
	}

	public String getModuleName() {
		return ((this.mainDef == null) ? null : this.mainDef.getModuleName());
	}
}